package com.oazon.moco.lan.core.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

import android.content.Context;

import com.oazon.common.Logger;

class DiscoverySender {
    private static final String TAG = "DiscoverySender";

    final static private int RETRY_COUNT = 1;
    final static private int RETRY_BROADCAST_INTERVAL = 100;
    final static private int RETRY_SEND_INTERVAL = 10;

    private Context mContext;
    private boolean mStoped;

    public DiscoverySender(Context context) {
        mContext = context;
    }
    
    public void start() {
        mStoped = false;
    }
    
    public void stop() {
        mStoped = true;
    }

    public void broadcastPacket(String data, int port) {
        try {
            InetAddress destAddr = InetAddress.getByName("255.255.255.255"); 
            Logger.v(TAG, "boradcast address:" + destAddr.getHostAddress());
            byte[] dataBytes = data.getBytes();
            DatagramPacket packet = new DatagramPacket(dataBytes, dataBytes.length,
                    destAddr, port);
            for (int i = 0; i < RETRY_COUNT; i++) {
                if (mStoped)
                    break;
                DatagramSocket broadcast = null;
                try {
                    broadcast = new DatagramSocket();;
                    broadcast.setBroadcast(true);
                    broadcast.send(packet);
                    Logger.d(TAG, "broad to 255.255.255.255 port:" + port + "Data:" + data);
                    Thread.sleep(RETRY_BROADCAST_INTERVAL);
                } catch (Exception e1) {
                    Logger.w(TAG, "broadcast packet failed!" + e1);
                } finally {
                    if (broadcast != null)
                        broadcast.close();
                }
            }
        } catch (Exception e) {
            Logger.w(TAG, "unknown address:" + e);
        } 
    }
    
    public void broadcastPacket(String data, int port, String[] targets, boolean isOffline) {
        for (String target : targets) {
            if (mStoped && !isOffline)
                break;
            try {
                InetAddress destAddr = InetAddress.getByName(target);
                byte[] dataBytes = data.getBytes();
                DatagramPacket packet = new DatagramPacket(dataBytes, dataBytes.length,
                        destAddr, port);
                for (int i = 0 ; i < RETRY_COUNT; i++) {
                    if (mStoped && !isOffline)
                        break;
                    DatagramSocket unicast = null;
                    try {
                        unicast = new DatagramSocket();;
                        unicast.send(packet);
                        Thread.sleep(RETRY_BROADCAST_INTERVAL);
                    } catch (Exception e1) {
                        Logger.w(TAG, "broadcast packet failed!" + e1);
                    } finally {
                        if (unicast != null)
                            unicast.close();
                    }
                }
            } catch (IOException e) {
                Logger.w(TAG, "unknown address! ip = " + target + ", " + e);
            } 
        }
    }

    public void sendPacket(String address, int port, String data) {
        try {
            byte[] dataBytes = data.getBytes();
            InetAddress ia = InetAddress.getByName(address);
            DatagramPacket message = new DatagramPacket(dataBytes, dataBytes.length, ia, port);
            for (int i = 0; i < RETRY_COUNT; i++) {
                if (mStoped)
                    break;
                DatagramSocket unicast = null;
                try {
                    unicast = new DatagramSocket();;
                    unicast.send(message);
                    Thread.sleep(RETRY_SEND_INTERVAL);
                } catch (Exception e1) {
                    Logger.w(TAG, "broadcast packet failed!" + e1);
                } finally {
                    if (unicast != null)
                        unicast.close();
                }
            }
        } catch (Exception e) {
            Logger.w(TAG, "unknown address!" + e);
        }
    }
    
    public void sendPacketOnce(String address, int port, String data, boolean isOffline) {
        try {
            byte[] dataBytes = data.getBytes();
            InetAddress ia = InetAddress.getByName(address);
            DatagramPacket message = new DatagramPacket(dataBytes, dataBytes.length, ia, port);
            if (mStoped && !isOffline)
                return;
            DatagramSocket unicast = null;
            try {
                unicast = new DatagramSocket();;
                unicast.send(message);
            } catch (Exception e1) {
                Logger.w(TAG, "broadcast packet failed!" + e1);
            } finally {
                if (unicast != null)
                    unicast.close();
            }
        } catch (Exception e) {
            Logger.w(TAG, "unknown address!" + e);
        }
    }

    private static byte[] arrayToByteIP(int ai[])
    {
        byte abyte0[] = new byte[4];
        abyte0[0] = (byte)(255 & ai[0]);
        abyte0[1] = (byte)(255 & ai[1]);
        abyte0[2] = (byte)(255 & ai[2]);
        abyte0[3] = (byte)(255 & ai[3]);
        return abyte0;
    }
    
    private static int[] intToArrayIp(int value) {
        int[] result = new int[4];
        result[0] = value & 0xFF;
        result[1] = (value >> 8) & 0xFF;
        result[2] = (value >> 16) & 0xFF;
        result[3] = (value >> 24) & 0xFF;
        return result;
    }
    
}
